home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1998 June / SGI Freeware 1998 June.iso / dist / fw_ATxgopher.idb / usr / freeware / src / xgopher.1.3 / jobs.c.z / jobs.c
C/C++ Source or Header  |  1998-01-21  |  7KB  |  335 lines

  1. /* jobs.c
  2.    get some idea of the jobs spawned by Xgopher */
  3.  
  4.      /*---------------------------------------------------------------*/
  5.      /* Xgopher        version 1.3     08 April 1993                  */
  6.      /*                version 1.2     20 November 1992               */
  7.      /*                version 1.1     20 April 1992                  */
  8.      /*                version 1.0     04 March 1992                  */
  9.      /* X window system client for the University of Minnesota        */
  10.      /*                                Internet Gopher System.        */
  11.      /* Allan Tuchman, University of Illinois at Urbana-Champaign     */
  12.      /*                Computing and Communications Services Office   */
  13.      /* Copyright 1992, 1993 by                                       */
  14.      /*           the Board of Trustees of the University of Illinois */
  15.      /* Permission is granted to freely copy and redistribute this    */
  16.      /* software with the copyright notice intact.                    */
  17.      /*---------------------------------------------------------------*/
  18.  
  19. #ifdef DEBUG
  20. void            listJobs(
  21. );
  22. #endif
  23.  
  24. #include <stdio.h>
  25.  
  26. #include "conf.h"
  27. #include "gopher.h"
  28. #include "osdep.h"
  29. #include "jobs.h"
  30. #include <signal.h>
  31.  
  32. #include <sys/wait.h>
  33. #include <sys/time.h>
  34. #ifndef ISCX
  35. #include <sys/resource.h>
  36. #endif
  37.  
  38.  
  39. #if        defined(SYSV) || defined(SVR4) || defined(__convex__) || defined(__bsdi__) || defined(sgi) || defined(linux) || defined(DEC)
  40. #define    WAITSTATUS_INT
  41. #else
  42. #undef    WAITSTATUS_INT
  43. #endif
  44.  
  45. static jobList *jobs = (jobList *) NULL;
  46.  
  47.  
  48. /* childIsGone
  49.    handle signal noting the termination of a child process */
  50.  
  51. void
  52. childIsGone()
  53. {
  54.     waitOnChildren();
  55.  
  56. #ifndef SIGCLD
  57. #define SIGCLD SIGCHLD
  58. #endif
  59.     /* some Unix flavors need to reset the signal handler
  60.        after one is delivered. */
  61.  
  62.     signal (SIGCLD, childIsGone);
  63.  
  64. }
  65.  
  66.  
  67. /* addJob
  68.    add the given pid to the internal job data structures */
  69.  
  70. void
  71. addJob(t, pid)
  72. char        t;
  73. PID_TYPE    pid;
  74. {
  75.     static    firstTime = TRUE;
  76.     jobList    *j=(jobList *) malloc(sizeof(jobList));
  77.  
  78.     if (firstTime) {
  79.  
  80.         /* set signal handler to catch child processes, note their
  81.            termination (prevent zombie status), and remove them from
  82.            the job queue. */
  83.  
  84. #ifndef SIGCLD
  85. #define SIGCLD SIGCHLD
  86. #endif
  87.         signal (SIGCLD, childIsGone);
  88.  
  89.         firstTime = FALSE;
  90.     }
  91.  
  92.     j->jobType = t;
  93.     j->pid       = pid;
  94.     j->next    = jobs;
  95.  
  96.     jobs = j;
  97.  
  98. }
  99.  
  100.  
  101. /* removeJob
  102.    remove the given pid from the internal job data structures */
  103.  
  104. BOOLEAN
  105. removeJob(pid)
  106. PID_TYPE    pid;
  107. {
  108.     jobList *j, *jp;
  109.  
  110.     jp = NULL;
  111.     for (j=jobs; (j != (jobList *) NULL  &&  j->pid != pid); j=j->next){
  112.         jp = j;
  113.     }
  114.  
  115.     if (j != NULL) {        /* pid in list */
  116. #ifdef DEBUG
  117.         fprintf (stderr, "Remove process %d (type %c)\n",
  118.                 j->pid, j->jobType);
  119. #endif    /* DEBUG */
  120.         if (jp == NULL) {    /* first element */
  121.             jobs = j->next;
  122.         } else {
  123.             jp->next = j->next;
  124.         }
  125.         free(j);
  126.         return TRUE;
  127.     } else {
  128.         return FALSE;
  129.     }
  130. }
  131.  
  132.  
  133. /* findJobPID
  134.    return the item type of the child with the supplied pid */
  135.  
  136. char    
  137. findJobPID(pid)
  138. PID_TYPE    pid;
  139. {
  140.     jobList *j;
  141.  
  142.     for (j=jobs; (j != (jobList *) NULL  &&  j->pid != pid); j=j->next){
  143.     }
  144.  
  145.     return (j == NULL) ? NO_TYPE : j->jobType;
  146. }
  147.  
  148.  
  149. /* findJobType
  150.    return the pid of the first child that matches the supplied type */
  151.  
  152. PID_TYPE
  153. findJobType(t)
  154. char        t;
  155. {
  156.     jobList *j;
  157.  
  158.     for (j=jobs; (j != (jobList *) NULL  &&  j->jobType != t); j=j->next){
  159.     }
  160.  
  161.     return (j == NULL ? NO_JOB: j->pid);
  162. }
  163.  
  164.  
  165. /* killItemProcess
  166.    terminate a specific child process */
  167.  
  168. void
  169. killItemProcess(pid)
  170. PID_TYPE    pid;
  171. {
  172. #ifdef DEBUG
  173.     fprintf (stderr, "killing process %d\n", pid);
  174. #endif    /* DEBUG */
  175.     if (pid > 1) kill(pid, KILL_SIGNAL);
  176.     waitOnChildren();
  177. }
  178.  
  179.  
  180. /* killAllItemType
  181.    terminate all items that match the supplied type */
  182.  
  183. void
  184. killAllItemType(t)
  185. char        t;
  186. {
  187.     jobList *j, *nj;
  188.  
  189.     /* WARNING: the kill will do a wait(2), then remove the 
  190.        job from this job queue.  So in stepping through the elements 
  191.        be sure never to reference a jobList* after the kill.
  192.        In particular, grab the "next" field before killing. */
  193.  
  194. #ifdef DEBUG
  195.     fprintf (stderr, "killing processes for item type %c\n", t);
  196.     listJobs();
  197. #endif    /*  DEBUG */
  198.  
  199.     nj = jobs;
  200.     while ( nj != (jobList *) NULL ){
  201.         j = nj;
  202.         nj = j->next;
  203.         if (j->jobType == t) {
  204.             killItemProcess(j->pid);
  205.         }
  206.     }
  207.  
  208. }
  209.  
  210.  
  211. /* killAllItemProcesses
  212.    terminate all child processes. */
  213.  
  214. void
  215. killAllItemProcesses()
  216. {
  217.     jobList *j, *nj;
  218.  
  219.     /* WARNING: the kill will do a wait(2), then remove the 
  220.        job from this job queue.  So in stepping through the elements 
  221.        be sure never to reference a jobList* after the kill.
  222.        In particular, grab the "next" field before killing. */
  223. #ifdef DEBUG
  224.     fprintf (stderr, "killing all processes\n");
  225.     listJobs();
  226. #endif    /*  DEBUG */
  227.  
  228. #ifdef DEBUG
  229.     fprintf (stderr, "start: jobs=0x%x\n", jobs);
  230. #endif /* DEBUG */
  231.     nj = jobs;
  232.     while ( nj != (jobList *) NULL ) {
  233.         j = nj;
  234.         nj = j->next;
  235. #ifdef DEBUG
  236.         fprintf (stderr, "next iter: j=0x%x, nj=0x%x\n", j, nj);
  237. #endif /* DEBUG */
  238.         killItemProcess(j->pid);
  239.     }
  240. }
  241.  
  242.  
  243. /* waitForJob
  244.    block until a specified job is completed */
  245.  
  246. void
  247. waitForJob(waitPID)
  248. PID_TYPE    waitPID;
  249. {
  250.     PID_TYPE    donePID;
  251. #ifndef    WAITSTATUS_INT
  252.     union wait    status;
  253. #else
  254.     int        status;
  255. #endif    /* ! WAITSTATUS_INT */
  256.  
  257.     do {
  258.         donePID = wait(&status);
  259. #ifdef        DEBUG
  260.         fprintf (stderr, "Process %d is done\n", donePID);
  261. #endif        /*  DEBUG */
  262.         if (donePID != (PID_TYPE) 0) {
  263.             removeJob(donePID);
  264.         }
  265.  
  266.     } while (donePID != waitPID);
  267. }
  268.  
  269.  
  270. /* waitOnChildren
  271.    handle request or signal noting the termination of a child process */
  272.  
  273. void
  274. waitOnChildren()
  275. {
  276.     PID_TYPE    donePID;
  277.  
  278. #ifndef    WAITSTATUS_INT
  279.     union wait    status;
  280. #else
  281.     int        status;
  282. #endif    /* ! WAITSTATUS_INT */
  283.  
  284. #if    !defined(macII) && !defined(CRAY) && !defined(SVR4) && !defined(SYSV)
  285. #define WAIT3
  286.     struct rusage    rusage;
  287. #endif    /* MacII, CRAY, SVR4, SYSV */
  288.  
  289.     
  290.     do {
  291.  
  292. #if        defined(macII)
  293.         donePID = wait3(&status, WNOHANG, NULL);
  294. #else        /* not macII */
  295. #  if        !defined(WAIT3)
  296.         donePID = waitpid(-1, &status, WNOHANG);
  297. #  else        /* use wait3 call for others */
  298.         donePID = wait3(&status, WNOHANG, &rusage);
  299. #  endif    /* other */
  300. #endif        /* */
  301.  
  302.         
  303. #ifdef DEBUG
  304.         fprintf (stderr, "Process %d is done\n", donePID);
  305. #endif    /*  DEBUG */
  306.         if (donePID > (PID_TYPE) 0) {
  307. #ifndef WIFEXITED
  308. #define WIFEXITED(x)    (! ((x) & 0xff))
  309. #endif
  310.             if (WIFEXITED(status)) {
  311.                 removeJob(donePID);
  312.             }
  313.         }
  314.  
  315.     } while (donePID > (PID_TYPE) 0);
  316. }
  317.  
  318.  
  319. #ifdef DEBUG
  320. void
  321. listJobs()
  322. {
  323.     jobList *j;
  324.  
  325.     fprintf (stderr, "Active processes started by Xgopher\n");
  326.  
  327.     for (j=jobs; j != (jobList *) NULL; j=j->next){
  328.         fprintf (stderr, "    pid: %6d    Xgopher item type \'%c\'\n",
  329.                 j->pid, j->jobType);
  330.     }
  331.  
  332.     fprintf (stderr, "End of active process list\n");
  333. }
  334. #endif
  335.